﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Web;
using System.IO;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

namespace ClassCommon
{
    /// <summary>
    /// EmailHelper 帮助类
    /// 郭青松
    /// 2018年6月23日
    /// </summary>
    public class EmailHelper
    {
        /// <summary>
        /// 发送邮件
        /// </summary>
        /// <param name="toEmail">接受者邮件地址</param>
        /// <param name="subject">邮件主题</param>
        /// <param name="emailBody">邮件内容</param>
        /// <returns></returns>
        public static void Send(string toEmail, string subject, string emailBody)
        {
            // 邮件发送的检测
            if (string.IsNullOrEmpty(toEmail)) throw new ArgumentNullException("toEmail is null");
            if (string.IsNullOrEmpty(subject)) throw new ArgumentNullException("subject is null");
            if (string.IsNullOrEmpty(emailBody)) throw new ArgumentNullException("emailbody is null");

            // 邮箱格式检测
            if (!RegexHelper.isEmail(toEmail))
            {
                throw new ArgumentException("邮箱格式错误!");
            }

            try
            {
                EmailInstance instance = new EmailInstance(toEmail, subject, emailBody);
                instance.Send();
            }
            catch (Exception ex)
            {
                HttpContext.Current.Response.Write(ex.Message);
                throw ex;
            }
        }

        /// <summary>
        /// 根据用户的邮箱地址返回邮箱登录链接
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public static string GetEmailLink(string email)
        {
            if (email.Contains("@163")) return "https://mail.163.com";
            if (email.Contains("@126")) return "https://mail.126.com/";
            if (email.Contains("@qq")) return "https://mail.qq.com";
            if (email.Contains("@sina")) return "https://mail.sina.com.cn/";

            return "unknow";
        }

        /// <summary>
        /// 获得替换后的邮箱模板
        /// </summary>
        /// <param name="findPasswordLink"></param>
        /// <param name="emailName"></param>
        /// <returns></returns>
        public static string GetEmailBody(string findPasswordLink, string emailName)
        {
            string emailFilePath = HttpContext.Current.Server.MapPath("/Static/FindPassword/EmailContentTemplate.html");
            string emailTemplate = string.Empty;
            using (StreamReader sr = new StreamReader(emailFilePath, Encoding.UTF8))
            {
                emailTemplate = sr.ReadToEnd();
            }

            // 替换用户账号
            emailTemplate = emailTemplate.Replace("{$userAccount}", emailName);
            emailTemplate = emailTemplate.Replace("{$link}", findPasswordLink);

            return emailTemplate;
        }
    }

    /// <summary>
    /// Author : 郭青松
    /// Date : 2018年6月23日 
    /// Descr : 邮件发送实体类
    /// </summary>
    internal class EmailInstance
    {
        #region [ 属性(发送Email相关) ]
        private string _SmtpHost = string.Empty;
        private int _SmtpPort = -1;
        private string _FromEmailAddress = string.Empty;
        private string _FormEmailPassword = string.Empty;
        private string _EmpowersCode = string.Empty;// 邮箱授权码 

        /// <summary>
        /// 客户端通过smtp 协议发送邮件，现在需要使用授权码，而不是邮箱的密码
        /// </summary>
        public string EmpowersCode
        {
            get
            {
                if (string.IsNullOrEmpty(_EmpowersCode))
                {
                    _EmpowersCode = ConfigurationManager.AppSettings["EmpowersCode"];
                }
                return _EmpowersCode;
            }
        }

        /// <summary>
        /// smtp 服务器 
        /// </summary>
        public string SmtpHost
        {
            get
            {
                if (string.IsNullOrEmpty(_SmtpHost))
                {
                    _SmtpHost = ConfigurationManager.AppSettings["SmtpHost"];
                }
                return _SmtpHost;
            }
        }
        /// <summary>
        /// smtp 服务器端口  默认为25
        /// </summary>
        public int SmtpPort
        {
            get
            {
                if (_SmtpPort == -1)
                {
                    if (!int.TryParse(ConfigurationManager.AppSettings["SmtpPort"], out _SmtpPort))
                    {
                        _SmtpPort = 25;
                    }
                }
                return _SmtpPort;
            }
        }
        /// <summary>
        /// 发送者 Eamil 地址
        /// </summary>
        public string FromEmailAddress
        {
            get
            {
                if (string.IsNullOrEmpty(_FromEmailAddress))
                {
                    _FromEmailAddress = ConfigurationManager.AppSettings["FromEmailAddress"];
                }
                return _FromEmailAddress;
            }
        }

        /// <summary>
        /// 发送者 Eamil 密码
        /// </summary>
        public string FormEmailPassword
        {
            get
            {
                if (string.IsNullOrEmpty(_FormEmailPassword))
                {
                    _FormEmailPassword = ConfigurationManager.AppSettings["FromEmailPassword"];
                }
                return _FormEmailPassword;
            }
        }
        #endregion

        #region [ 属性(邮件相关) 2]
        /// <summary>
        /// 收件人 Email 列表，多个邮件地址之间用 半角逗号 分开
        /// </summary>
        public string ToList { get; set; }
        /// <summary>
        /// 邮件的抄送者，支持群发，多个邮件地址之间用 半角逗号 分开
        /// </summary>
        public string CCList { get; set; }
        /// <summary>
        /// 邮件的密送者，支持群发，多个邮件地址之间用 半角逗号 分开
        /// </summary>
        public string BccList { get; set; }
        /// <summary>
        /// 邮件标题
        /// </summary>
        public string Subject { get; set; }
        /// <summary>
        /// 邮件正文
        /// </summary>
        public string Body { get; set; }

        private bool _IsBodyHtml = true;
        /// <summary>
        /// 邮件正文是否为Html格式
        /// </summary>
        public bool IsBodyHtml
        {
            get { return _IsBodyHtml; }
            set { _IsBodyHtml = value; }
        }
        /// <summary>
        /// 附件列表
        /// </summary>
        public List<Attachment> AttachmentList { get; set; }
        #endregion

        #region [ 构造函数 ]
        /// <summary>
        /// 构造函数 (body默认为html格式)
        /// </summary>
        /// <param name="toList">收件人列表</param>
        /// <param name="subject">邮件标题</param>
        /// <param name="body">邮件正文</param>
        public EmailInstance(string toList, string subject, string body)
        {
            this.ToList = toList;
            this.Subject = subject;
            this.Body = body;
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="toList">收件人列表</param>
        /// <param name="subject">邮件标题</param>
        /// <param name="isBodyHtml">邮件正文是否为Html格式</param>
        /// <param name="body">邮件正文</param>
        public EmailInstance(string toList, string subject, bool isBodyHtml, string body)
        {
            this.ToList = toList;
            this.Subject = subject;
            this.IsBodyHtml = isBodyHtml;
            this.Body = body;
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="toList">收件人列表</param>
        /// <param name="ccList">抄送人列表</param>
        /// <param name="bccList">密送人列表</param>
        /// <param name="subject">邮件标题</param>
        /// <param name="isBodyHtml">邮件正文是否为Html格式</param>
        /// <param name="body">邮件正文</param>
        public EmailInstance(string toList, string ccList, string bccList, string subject, bool isBodyHtml, string body)
        {
            this.ToList = toList;
            this.CCList = ccList;
            this.BccList = bccList;
            this.Subject = subject;
            this.IsBodyHtml = isBodyHtml;
            this.Body = body;
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="toList">收件人列表</param>
        /// <param name="ccList">抄送人列表</param>
        /// <param name="bccList">密送人列表</param>
        /// <param name="subject">邮件标题</param>
        /// <param name="isBodyHtml">邮件正文是否为Html格式</param>
        /// <param name="body">邮件正文</param>
        /// <param name="attachmentList">附件列表</param>
        public EmailInstance(string toList, string ccList, string bccList, string subject, bool isBodyHtml, string body, List<Attachment> attachmentList)
        {
            this.ToList = toList;
            this.CCList = ccList;
            this.BccList = bccList;
            this.Subject = subject;
            this.IsBodyHtml = isBodyHtml;
            this.Body = body;
            this.AttachmentList = attachmentList;
        }
        #endregion

        #region [ 发送邮件 ]
        /// <summary>
        /// 发送邮件
        /// </summary>
        /// <returns></returns>
        public void Send()
        {
            #region 发送邮件版本1 net_io_connectionclosed
            //MailAddress ma_from = new MailAddress(this.FromEmailAddress, "[华志创云排课]-邮箱密码找回");
            //MailAddress ma_to = new MailAddress(this.ToList, "");
            //string password = this.FormEmailPassword; // 发送邮箱的密码
            //string s_subject = this.Subject;
            //string body = this.Body;

            //SmtpClient client = new SmtpClient()
            //{
            //    Host = this.SmtpHost,
            //    Port = this.SmtpPort,
            //    EnableSsl = true,
            //    DeliveryMethod = SmtpDeliveryMethod.Network,
            //    UseDefaultCredentials = false,
            //    Credentials = new NetworkCredential(ma_from.Address, password)
            //};

            //using (MailMessage mail = new MailMessage(ma_from, ma_to)
            //{
            //    Subject = this.Subject,
            //    Body = this.Body
            //})
            //{

            //    try
            //    {
            //        client.Send(mail);
            //    }
            //    catch (Exception ex)
            //    {
            //        HttpContext.Current.Response.Write(ex.Message);
            //        throw;
            //    }
            //}
            #endregion

            #region 发送邮件版本2 net_io_connectionclosed
            ////ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
            ////实例化一个SmtpClient
            //using (SmtpClient smtp = new SmtpClient())
            //{
            //    smtp.DeliveryMethod = SmtpDeliveryMethod.Network;   //将smtp的出站方式设为 Network
            //    // smtp.EnableSsl = true;                             //smtp服务器是否启用SSL加密
            //    smtp.Host = this.SmtpHost;                          //指定 smtp 服务器地址
            //    smtp.Port = this.SmtpPort;                          //指定 smtp 服务器的端口，默认是25，如果采用默认端口，可省去
            //    // smtp.Timeout = 10000;
            //    // smtp.UseDefaultCredentials = true;                  //如果你的SMTP服务器不需要身份认证，则使用下面方式，不过，目前基本没有不需要认证的了
            //    smtp.Credentials = new NetworkCredential(this.FromEmailAddress, this.FormEmailPassword);    //如果需要认证，则用下面的方式


            //}

            #endregion
            #region 发送邮件版本3 可以发送 原因，最新的System.Web.Net 下的mailMessage 不支持 465 的ssl 模式，需要使用比较旧的 在 System.Web.Mail命令空间下的 MailMessage发送邮件信息
            System.Web.Mail.MailMessage mm = new System.Web.Mail.MailMessage();
            // MailMessage mm = new MailMessage(); //实例化一个邮件类
            mm.Priority = System.Web.Mail.MailPriority.High; //邮件的优先级，分为 Low, Normal, High，通常用 Normal即可
            mm.From = this.FromEmailAddress;
            mm.To = this.ToList;
            mm.Subject = this.Subject;     //邮件标题   
            mm.BodyFormat = System.Web.Mail.MailFormat.Html;
            mm.BodyEncoding = Encoding.UTF8;    //邮件正文的编码， 设置不正确， 接收者会收到乱码
            mm.Body = this.Body;                            //邮件正文

            mm.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1"); //身份验证
            mm.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", mm.From); //邮箱登录账号，这里跟前面的发送账号一样就行
            mm.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", this.FormEmailPassword); //这个密码要注意：如果是一般账号，要用授权码；企业账号用登录密码
            mm.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", this.SmtpPort);//端口
            mm.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpusessl", "true");//SSL加密
            System.Web.Mail.SmtpMail.SmtpServer = this.SmtpHost;
            System.Web.Mail.SmtpMail.Send(mm);

            #endregion
        }
        #endregion
    }
}
